//: [Previous](@previous)
import Foundation
//: ## 闭包表达式(Closure Expression)
// 在swift中, 可以通过func定义一个函数, 也可以通过闭包表达式定义一个函数
/**
 闭包表达式的构成:
 
    {
        (函数列表) -> 返回值类型 in
        函数体代码
    }
 
 1.以大括号开始,以大括号结束
 2.in 是作用区分开函数体.返回值类型 和 函数体代码的, in前面的是函数列表,返回值类型, in后面的是函数体代码
 */
//普通函数
func sum(_ v1: Int, _ v2: Int) -> Int { v1 + v2}
sum(10, 20)

//同作用的闭包表达式1
var fn = {
    (v1: Int, v2: Int) -> Int in
    return v1 + v2
}
fn(10, 20)

//同作用的闭包表达式2(有点像匿名函数,不常用), 直接大括号开始
//{
//    (v1: Int, v2: Int) -> Int in
//    return v1 + v2
//}(10, 20)
//: ## 闭包表达式的简写
func exec(v1: Int, v2: Int, fn: (Int, Int) -> Int) {
    print(fn(v1, v2))
}// 需求是传入2个数,让他们相加
exec(v1: 10, v2: 20, fn: {
    (v1: Int, v2: Int) -> Int in
    return v1 + v2
})

//省略参数的类型 和 参数左右的小括号
exec(v1: 10, v2: 20, fn: {
    v1, v2 in
    return v1 + v2
})
    
//因为函数体比较简单是个单一表达式,所以可以直接省略return
exec(v1: 10, v2: 20, fn: {
    v1, v2 in
    v1 + v2
})

//因为整个闭包表达式简单,只是单纯的2个参数相加,所以可以用美元符$0去代表第一个参数 然后直接相加即可
exec(v1: 10, v2: 20, fn: { $0 + $1 })

//就是表达为相加
exec(v1: 10, v2: 20, fn: + )
//: ## 尾随闭包
// 如果将一个很长的闭包表达式作为函数的最后一个实参, 使用尾随闭包可以增强函数的可读性. 就是把最后一个参数是闭包表达式的先拿出来不要了,其他参数用小括号先括起来,最后面单独给闭包表达式用大括号再括起来,这样子看前面的小括号就可以很好的看清楚参数了
// 尾随闭包是一个被书写在函数调用括号外面(后面)的闭包表达式
func exec1(v1: Int, v2: Int, fn: (Int, Int) -> Int) {
    print(fn(v1, v2))
}

exec1(v1: 10, v2: 20) { v1, v2 in
    v1 + v2
}

// 如果闭包表达式是函数的唯一实参, 而且使用了尾随闭包的语法, 那就不需要在函数名后面写圆括号
func exec2(fn: (Int, Int) -> Int) {
    print(fn(1, 2))
}
//完整的写法
exec2(fn: {$0 + $1})
//省略了闭包的名称fn
exec2(){$0 + $1}
//省略了圆括号
exec2 { $0 + $1 }
//目前系统的默认
//exec2 { <#Int#>, <#Int#> in
//    <#code#>
//}
//: ## 示例 - 数组的排序(利用闭包表达式)
var nums = [1, 2, 3, 4, 5]
nums.sort()
//print(nums) //[1, 2, 3, 4, 5]
//数组.sort() 是系统给出的排序,从小到大,我们可以通过by后面加上条件去改变排序
// nums.sort(by: <#T##(Int, Int) throws -> Bool#>) //这个是系统方法的内容

// 这个方法的意思是,判断i1 > i2 的真假,返回BOOL
func cmp(i1: Int, i2: Int) -> Bool {
    return i1 > i2
}
//上面方法的格式符合nums.sort(by: <#T##(Int, Int) throws -> Bool#>)的by
nums.sort(by: cmp)
//print(nums) // [5, 4, 3, 2, 1]

//直接在by后面写的闭包表达式(写法1,完整的写法)
nums = [1, 2, 3, 4, 5, 9, 6]
nums.sort(by: {
    (i1: Int, i2: Int) -> Bool in
    return i1 > i2
})
//print(nums)//[9, 6, 5, 4, 3, 2, 1]

//直接在by后面写的闭包表达式(写法2,比较合理工作的写法)
nums = [1, 2, 3, 4, 5, 9, 6]
nums.sort { i1, i2 in
    i1 < i2
}
//print(nums)// [1, 2, 3, 4, 5, 6, 9]

//其他写法 (都是升序,<就是左比右小,>就是左比右大降序)
nums.sort(by: {i1, i2 in return i1 < i2})
nums.sort(by: {i1, i2 in i1 < i2})
nums.sort(by: {$0 < $1})
nums.sort(by:  < )
nums.sort { i1, i2 in
    i1 < i2
}
//: ## 省略参数(知道就行)
func exec3(fn: (Int, Int)->Int) {
    print(fn(1, 2))
}
//正常写法,结果是让v1+v2
exec3 { v1, v2 in
    v1 + v2
}
//但是假如需求是只要一个固定结果10呢
exec3 { 
    _, _ in
    10
}
//用不到的实参就可以用下划线省略掉,这就是省略参数






//: [Next](@next)
